from multiprocessing import Process, Queue, Pipe, Lock
import os, time
# def f(name):
#     print('hello', name)
# if __name__ == '__main__':
#     p = Process(target=f, args=('world',))
#     #启动进程
#     p.start()
#     #实现进程间的同步，等待所有进程退出
#     p.join()
# 在启动进程的过程中，需要考虑执行顺序的问题，正常情况下是主进程先执行，子进程后执行
# def run():
#     print("子进程开启")
#     time.sleep(2)
#     print("子进程结束")
#
# if __name__ == "__main__":
#     print("主进程启动")
#     p = Process(target=run)
#     p.start()
#     print("主进程结束")

# def f(q):
#     q.put([11, None, 'lily'])
# if __name__ == '__main__':
#     q = Queue()
#     p = Process(target=f, args=(q,))
#     p.start()
#     print(q.get())
#     p.join()

# TODO  Pipe类
'''
Pipe()函数有一个可选参数 duplex，参数 duplex 的默认值为 True，表示该管道是双向的，
即两个对象都可以发送和接收消息。如果把参数 duplex 设置为 False ，表示该管道是单向的，即 conn1 只能用于接收消息，conn2 只能用于发送消息
'''
# def f(conn):
#     conn.send([11, None, 'lily'])
#     conn.close()
#
# if __name__ == '__main__':
#     conn1, conn2 = Pipe()
#     p = Process(target=f, args=(conn2,))
#     p.start()
#     print(conn1.recv())
#     p.join()
# 从以上示例可以看出，Queue 和 Pipe 拥有相似的功能。但在日常开发中，两者使用的场景有所不同，Pipe 多用于两个进程间通信，而 Queue 则多用于两个及以上进程间的通信

'''
由于多线程共享进程的资源和地址空间，因此，在对这些公共资源进行操作时，为了防止这些公共资源出现异常的结果，必须考虑线程的同步和互斥问题。

为了保证进程间的同步，我们可以使用 Lock 类给线程或者进程加锁。Lock 返回的是一个非递归锁对象，
Lock 实际上是一个工厂函数。它返回由默认上下文初始化的 multiprocessing.synchronize.Lock 对象。

一旦某一个进程或者线程拿到了锁，后续的任何其他进程或线程的其他请求都会被阻塞直到锁被释放。
'''
'''
当多个线程同时执行lock.acquire()时，只有一个线程能成功地获取锁，然后继续执行代码，其他线程就继续等待直到获得锁为止。

获得锁的线程用完后一定要释放锁，否则那些苦苦等待锁的线程将永远等待下去，成为死线程。所以我们用try...finally来确保锁一定会被释放
'''

def f(l, i):
    l.acquire()
    try:
        print('this is', i)
    finally:
        l.release()

if __name__ == '__main__':
    lock = Lock()

    for num in range(10):
        Process(target=f, args=(lock, num)).start()

'''
更多关于multiprocessing多进程请查看示例： https://blog.csdn.net/brucewong0516/article/details/85796073
'''